             package com.java.diagnostics.visualizer.gc.hp.parser;
             
             import com.java.diagnostics.visualizer.data.DataLevel;
             import com.java.diagnostics.visualizer.data.SourceData;
             import com.java.diagnostics.visualizer.data.UnstructuredData;
             import com.java.diagnostics.visualizer.exceptions.GCAndMemoryVisualizerException;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.factory.SourceDataFactory;
             import com.java.diagnostics.visualizer.gc.solarissupport.util.Messages;
             import com.java.diagnostics.visualizer.impl.factory.LogFactory;
             import com.java.diagnostics.visualizer.parser.vgc.VGCDataManager;
             import com.java.diagnostics.visualizer.parser.vgc.VGCParserPreferenceHelper;
             import com.java.diagnostics.visualizer.parser.vgc.VGCPlainTextParser;
             import com.java.diagnostics.visualizer.parser.vgc.constants.VGCGCReasons;
             import com.java.diagnostics.visualizer.parser.vgc.constants.VGCGCScopes;
             import com.java.diagnostics.visualizer.properties.OutputProperties;
             import com.java.diagnostics.visualizer.sources.Source;
             import java.io.BufferedReader;
             import java.text.MessageFormat;
             import java.util.logging.Level;
             import java.util.logging.Logger;
             import java.util.regex.Matcher;
             import java.util.regex.Pattern;
             
             public class InstanceHPVGCParser
               extends VGCPlainTextParser
             {
               private static final String DERIVED_FROM_EDEN_0_AND_SURVIVOR_1 = Messages.getString("InstanceHPVGCParser.derived.from.eden.and.survivor");
               
               private static final String VERSION = Messages.getString("HPVGCParser.hp.version");
               
               private static final String PRE_142_VERSION = Messages.getString("HPVGCParser.hp.older.version");
               
               private boolean didVersion = false;
               
               public static final Logger TRACE = LogFactory.getTrace(InstanceHPVGCParser.class);
               
               protected static final String AF_OPEN = "<af";
               
               protected static final String CON_OPEN = "<con";
               
               protected static final String SYS_OPEN = "<sys";
               
               public static final String GC = "<GC:";
               
               public static final String GCH = "<GCH:";
               
               private static final Pattern GC_LINE_REGEX = Pattern.compile("<GC: ([0-9][0-9]*) ([0-9][0-9]*)  ([0-9][0-9]*\\.[0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*\\.[0-9][0-9]*) ([0-9][0-9]*\\.[0-9][0-9]*) >");
               
               private static final Pattern GC_LINE_REGEX_2 = Pattern.compile("<GC: ([0-9][0-9]*) ([0-9][0-9]*\\.[0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*) ([0-9][0-9]*\\.[0-9][0-9]*) >");
               
               private static final Pattern VERSION_REGEX = Pattern.compile("<GCH: vmrelease=\"(.*)\"");
               
               private static final Pattern START_TIME_REGEX = Pattern.compile("<GCH: starttime=\"(.*)\"");
               
               private double previousNurserySize = -1.0D;
               private double previousPreviousNurserySize = -2.0D;
               
               private double previousTenuredSize = -1.0D;
               private double previousPreviousTenuredSize = -2.0D;
               
               public SourceData parse(Source source, OutputProperties properties)
                 throws GCAndMemoryVisualizerException
               {
                 TRACE.entering(this.className, "parse");
                 this.filterSystemGCs = PLUGIN_PREFERENCES.getFilterSystemGCs();
                 
                 String line = null;
                 try {
                   String variantIdentifier = source.getVariantIdentifier();
                   this.sourceData = 
                     SOURCE_DATA_FACTORY.createSourceData(variantIdentifier);
                   this.dataManager = new VGCDataManager(source, this.sourceData, properties);
                   
                   BufferedReader reader = source.getSafeBufferedStreamReader();
                   
                   line = reader.readLine();
                   
                   while (line != null)
                   {
                     handleLine(line, reader);
                     
                     line = reader.readLine();
                   }
                   
                   writeOutSourceData();
                   
                   if (this.isGoodData) {
                     this.dataManager.ensureExistanceOf("VGCLabels.jvm.restarts");
                     this.dataManager.ensureExistanceOf("VGCLabels.gc.reasons");
                     this.dataManager.complete();
                   }
                   
                   reader.close();
                 } catch (Exception e) {
                   TRACE.warning(line);
                   e.printStackTrace();
                   TRACE.log(Level.WARNING, 
                     Messages.getString("SunVGCParser.caught.exception"), e);
                   this.sourceData = null;
                 }
                 
                 TRACE.exiting(this.className, "parse");
                 return this.sourceData;
               }
               
               private void handleLine(String line, BufferedReader reader)
                 throws GCAndMemoryVisualizerException
               {
                 Matcher gcMatcher = GC_LINE_REGEX.matcher(line);
                 boolean isGCOrFullGC = gcMatcher.matches();
                 if (isGCOrFullGC) {
                   handle142line(gcMatcher);
                 } else {
                   gcMatcher = GC_LINE_REGEX_2.matcher(line);
                   
                   isGCOrFullGC = gcMatcher.matches();
                   if (isGCOrFullGC) {
                     handle131line(gcMatcher);
                   }
                   else {
                     Matcher versionMatcher = VERSION_REGEX.matcher(line);
                     if (versionMatcher.matches()) {
                       this.didVersion = true;
                       String version = VERSION + " " + 
                         versionMatcher.group(1);
                       UnstructuredData versionData = factory
                         .createUnstructuredData("VGCLabels.version", 
                         Messages.getString("VGCLabels.version"), version);
                       this.sourceData.addData(versionData, DataLevel.VARIANT);
                     }
                     else
                     {
                       Matcher startMatcher = START_TIME_REGEX.matcher(line);
                       if (startMatcher.matches()) {
                         this.runningTimestamp = 
                           HPDateConverter.parseDate(startMatcher.group(1));
                       }
                     }
                   }
                 }
               }
               
               private void handle131line(Matcher gcMatcher)
               {
                 this.isGoodData = true;
                 
                 double timestamp = Double.parseDouble(gcMatcher.group(2));
                 if (timestamp < this.previousTimestamp) {
                   logRestart();
                 }
                 setCurrentTimestamp(timestamp);
                 int hpScope = Integer.parseInt(gcMatcher.group(1));
                 int scope = -1;
                 int reason = -1;
                 if (hpScope == -1) {
                   scope = VGCGCScopes.nameToInt("scavenger");
                 } else {
                   scope = VGCGCScopes.nameToInt("global");
                 }
                 
                 if (hpScope == 0) {
                   reason = VGCGCReasons.SYS_INT;
                   this.isSys = true;
                 }
                 else if (hpScope == 0) {
                   reason = VGCGCReasons.AF_INT;
                 }
                 
                 addDataPoint("VGCLabels.gc.scopes", scope, gcMatcher.group(1));
                 addDataPoint("VGCLabels.gc.reasons", reason, gcMatcher.group(1));
                 
                 double occupiedEdenBefore = Double.parseDouble(gcMatcher.group(6));
                 double occupiedSurvivorBefore = Double.parseDouble(gcMatcher.group(9));
                 double liveNurseryBefore = occupiedEdenBefore + occupiedSurvivorBefore;
                 String occupiedBeforeComment = MessageFormat.format(
                   DERIVED_FROM_EDEN_0_AND_SURVIVOR_1, new String[] {
                   String.valueOf(occupiedEdenBefore), 
                   String.valueOf(occupiedSurvivorBefore) });
                 addDataPoint("VGCLabels.live.nursery.heap.before.gc", liveNurseryBefore, 
                   occupiedBeforeComment);
                 
                 double occupiedEdenAfter = Double.parseDouble(gcMatcher.group(7));
                 double occupiedSurvivorAfter = Double.parseDouble(gcMatcher.group(10));
                 double liveNurseryAfter = occupiedEdenAfter + occupiedSurvivorAfter;
                 String occupiedAfterComment = MessageFormat.format(
                   DERIVED_FROM_EDEN_0_AND_SURVIVOR_1, new String[] {
                   String.valueOf(occupiedEdenAfter), 
                   String.valueOf(occupiedSurvivorAfter) });
                 addDataPoint("VGCLabels.live.nursery.heap.after.gc", liveNurseryAfter, 
                   occupiedAfterComment);
                 
                 double edenSize = Double.parseDouble(gcMatcher.group(8));
                 double survivorSize = Double.parseDouble(gcMatcher.group(11));
                 
                 addNurserySize(edenSize, survivorSize);
                 
                 addDataPoint("VGCLabels.request.sizes.which.triggered.failures", 
                   Double.parseDouble(gcMatcher.group(4)), "");
                 addDataPoint("VGCLabels.tenure.age", Double.parseDouble(
                   gcMatcher.group(5)), "");
                 
                 addDataPoint("VGCLabels.live.tenured.heap.before.gc", 
                   Double.parseDouble(gcMatcher.group(12)), "");
                 addDataPoint("VGCLabels.live.tenured.heap.after.gc", 
                   Double.parseDouble(gcMatcher.group(13)), "");
                 double tenuredSize = Double.parseDouble(gcMatcher.group(14));
                 addTenuredSize(tenuredSize);
                 
                 addDataPoint("VGCLabels.live.permanent.heap.before.gc", 
                   Double.parseDouble(gcMatcher.group(15)), "");
                 addDataPoint("VGCLabels.live.permanent.heap.after.gc", 
                   Double.parseDouble(gcMatcher.group(16)), "");
                 double permanentSize = Double.parseDouble(gcMatcher.group(17));
                 addPermanentSize(permanentSize);
                 addDataPoint("VGCLabels.pause.times.with.exclusive.access", 
                   Double.parseDouble(gcMatcher.group(18)), "");
                 
                 double flatHeapSize = edenSize + survivorSize + tenuredSize + 
                   permanentSize;
                 addFlatSize(flatHeapSize);
                 this.isSys = false;
               }
               
               private void handle142line(Matcher gcMatcher)
               {
                 this.isGoodData = true;
                 double timestamp = Double.parseDouble(gcMatcher.group(3));
                 int hpScope = Integer.parseInt(gcMatcher.group(1));
                 
                 if ((timestamp < this.previousTimestamp / 2.0D) && (hpScope != 3)) {
                   logRestart();
                 }
                 setCurrentTimestamp(timestamp);
                 
                 int scope = -1;
                 int reason = -1;
                 if (hpScope == 1) {
                   scope = VGCGCScopes.nameToInt("scavenger");
                 } else if (hpScope < 7) {
                   scope = VGCGCScopes.nameToInt("global");
                 }
                 else {
                   scope = VGCGCScopes.nameToInt("permanent");
                 }
                 
                 if ((hpScope < 3) || (hpScope == 4)) {
                   reason = VGCGCReasons.AF_INT;
                 } else {
                   reason = VGCGCReasons.CON_INT;
                 }
                 
                 addDataPoint("VGCLabels.gc.scopes", scope, gcMatcher.group(1));
                 addDataPoint("VGCLabels.gc.reasons", reason, gcMatcher.group(1));
                 
                 if (hpScope != 3)
                 {
                   double occupiedEden = Double.parseDouble(gcMatcher.group(7));
                   double occupiedSurvivor = Double.parseDouble(gcMatcher.group(10));
                   double liveNursery = occupiedEden + occupiedSurvivor;
                   String occupiedBeforeComment = MessageFormat.format(
                     DERIVED_FROM_EDEN_0_AND_SURVIVOR_1, new String[] {
                     String.valueOf(occupiedEden), 
                     String.valueOf(occupiedSurvivor) });
                   addDataPoint("VGCLabels.live.nursery.heap.before.gc", liveNursery, 
                     occupiedBeforeComment);
                   
                   addDataPoint("VGCLabels.request.sizes.which.triggered.failures", 
                     Double.parseDouble(gcMatcher.group(5)), "");
                   
                   addDataPoint("VGCLabels.live.tenured.heap.before.gc", 
                     Double.parseDouble(gcMatcher.group(13)), "");
                   double tenuredSize = Double.parseDouble(gcMatcher.group(15));
                   addTenuredSize(tenuredSize);
                   
                   addDataPoint("VGCLabels.live.permanent.heap.before.gc", 
                     Double.parseDouble(gcMatcher.group(16)), "");
                   double permanentSize = 
                     Double.parseDouble(gcMatcher.group(18));
                   addPermanentSize(permanentSize);
                   
                   double edenSize = Double.parseDouble(gcMatcher.group(9));
                   double survivorSize = Double.parseDouble(gcMatcher.group(12));
                   
                   addNurserySize(edenSize, survivorSize);
                   addDataPoint("VGCLabels.tenure.age", Double.parseDouble(
                     gcMatcher.group(6)), "");
                   
                   double flatHeapSize = edenSize + survivorSize + tenuredSize + 
                     permanentSize;
                   addFlatSize(flatHeapSize);
                 }
                 
                 double duration = Double.parseDouble(gcMatcher.group(20));
                 if (hpScope == 3)
                 {
                   setCurrentTimestamp(timestamp + duration);
                 }
                 else
                 {
                   addDataPoint("VGCLabels.pause.times.with.exclusive.access", 
                     Double.parseDouble(gcMatcher.group(19)), "");
                   addDataPoint("VGCLabels.pause.times.without.exclusive.access", 
                     duration, "");
                 }
                 
                 double occupiedEden = Double.parseDouble(gcMatcher.group(8));
                 double occupiedSurvivor = Double.parseDouble(gcMatcher.group(11));
                 double liveNursery = occupiedEden + occupiedSurvivor;
                 String occupiedAfterComment = MessageFormat.format(
                   DERIVED_FROM_EDEN_0_AND_SURVIVOR_1, new String[] {
                   String.valueOf(occupiedEden), 
                   String.valueOf(occupiedSurvivor) });
                 addDataPoint("VGCLabels.live.nursery.heap.after.gc", liveNursery, 
                   occupiedAfterComment);
                 
                 addDataPoint("VGCLabels.live.tenured.heap.after.gc", 
                   Double.parseDouble(gcMatcher.group(14)), "");
                 addDataPoint("VGCLabels.live.permanent.heap.after.gc", 
                   Double.parseDouble(gcMatcher.group(17)), "");
               }
               
               private void addNurserySize(double edenSize, double survivorSize)
               {
                 double nurserySize = edenSize + survivorSize;
                 if ((this.previousNurserySize > this.previousPreviousNurserySize) || 
                   (this.previousNurserySize < this.previousPreviousNurserySize)) {
                   if (this.previousNurserySize != -1.0D) {
                     addDataPoint("VGCLabels.nursery.size.before", 
                       this.previousNurserySize);
                   } else {
                     addDataPoint("VGCLabels.nursery.size.before", nurserySize);
                   }
                   this.previousPreviousNurserySize = this.previousNurserySize;
                 }
                 this.previousNurserySize = nurserySize;
                 
                 addDataPoint("VGCLabels.nursery.size", nurserySize, MessageFormat.format(
                   DERIVED_FROM_EDEN_0_AND_SURVIVOR_1, 
                   new String[] { String.valueOf(edenSize), 
                   String.valueOf(survivorSize) }));
               }
               
               private void addTenuredSize(double tenuredSize) {
                 if (this.previousTenuredSize != this.previousPreviousTenuredSize) {
                   if (this.previousTenuredSize != -1.0D) {
                     addDataPoint("VGCLabels.total.tenured.heap.before.gc", 
                       this.previousTenuredSize);
                   } else {
                     addDataPoint("VGCLabels.total.tenured.heap.before.gc", 
                       tenuredSize);
                   }
                   this.previousPreviousTenuredSize = this.previousTenuredSize;
                 }
                 this.previousTenuredSize = tenuredSize;
                 addDataPoint("VGCLabels.tenured.heap.size", tenuredSize, "");
               }
               
               private void addFlatSize(double flatHeapSize) {
                 addDataPoint("VGCLabels.flat.heap.size", flatHeapSize, "");
               }
               
               private void addPermanentSize(double permanentSize) {
                 addDataPoint("VGCLabels.permanent.heap.size", permanentSize, "");
               }
               
               protected void addVersion() {
                 if (!this.didVersion)
                 {
                   String version = PRE_142_VERSION;
                   UnstructuredData versionData = factory.createUnstructuredData(
                     "VGCLabels.version", Messages.getString("VGCLabels.version"), 
                     version);
                   this.sourceData.addData(versionData, DataLevel.VARIANT);
                 }
               }
               
               protected String getCategory()
               {
                 return "VGC";
               }
               
               protected boolean isTimeStampRelative()
               {
                 return true;
               }
             }


